import os
import ssl

if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
        getattr(ssl, '_create_unverified_context', None)): 
    os.environ['PYTHONHTTPSVERIFY'] = '0'
    ssl._create_default_https_context = ssl._create_unverified_context
    
import guidance
import json

def format_answer(answer):
    if isinstance(answer, str):
        return answer
    return ",".join([f"{t['label']}({t['score']})" for t in answer])

# Initialize the guidance object
guidance.llm = guidance.llms.OpenAI(
    "gpt-3.5-turbo-instruct",
    api_key="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", 
    api_base="http://154.12.55.160/v1/"
)

# Set up the prompt template
AN0_PROMPT = guidance("""
Analysis of a student's preference or ability ranking for various subjects based on the radar chart should provide:
- explain: a brief description in Chinese, max 50 words, of the radar chart;
- advise: recommendations in Chinese, max 80 words, in the tone of a teacher advising a student, based on the ranking.

INPUT:
"{{ranking_text}}" - A structured list of the student's subjects and their percentage scores.

OUTPUT:
```json
{
    "explain": "{{gen 'description' max_tokens=150 stop='"'}}",
    "advise": "{{gen 'recommendations' max_tokens=240 stop='"'}}"
}```""")

AN1_PROMPT = guidance("""
Analysis of a student's interest word cloud should provide:
- explain: a brief description in Chinese, max 50 words, of the word cloud chart;
- advise: recommendations in Chinese, max 80 words, in the tone of a teacher advising a student, for the student based on the word cloud.

INPUT:
"{{interests_text}}" - A structured list of the student's interests with their frequency proportion.

OUTPUT:
```json
{
    "explain": "{{gen 'description' max_tokens=150 stop='"'}}",
    "advise": "{{gen 'recommendations' max_tokens=240 stop='"'}}"
}```""")

AN2_PROMPT = guidance("""
Analysis of a student's time planning based on the treemap should provide:
- explain: a brief description in Chinese, max 50 words, of the treemap;
- advise: recommendations in Chinese, max 80 words, in the tone of a teacher advising a student, based on the time planning.

INPUT:
"{{time_planning_text}}" - A structured list of the student's activities and their time proportion.

OUTPUT:
```json
{
    "explain": "{{gen 'description' max_tokens=150 stop='"'}}",
    "advise": "{{gen 'recommendations' max_tokens=240 stop='"'}}"
}```""")

GEN_AN2_PROMPT = guidance("""
The Input is a student's response to their time planning. 
Based on the INPUT, please return a JSON {"result":[{"label": "${活动名称|MUST in INPUT}", "score": "${time_planning_weight|MUST be NUMBER}"]}}. 
If it cannot be determined, return an JSON with Chinese error {"error": "${原因|MUST be in Chinese}"}.
Note: Only one JSON should be provided. 

INPUT:
"{{time_planning_text}}" - A student's response to their time planning, containing activities in Chinese and their proportions.
OUTPUT:
{{gen 'json_output'}}""")

ANALYSIS_PROMPT = guidance("""
OUTPUT of a student's question and subject selection guide should provide:
- answer: A brief response in Chinese, max 50 words, in the tone of a teacher, used to answer the INPUT (the student's question).
- advise: 基于学生信息的科目选择推荐和得分的字符串,每个条目用逗号分隔,并按照${selection|从[政治,历史,地理,物理,化学,生物,技术]里选3门}(${score|最高为5分})的结构来组织.必须返回至少5个条目,例如:"物理化学政治(8),历史政治地理(5)".
- explain: A concise description in Chinese, max 80 words, in the tone of a teacher advising a student, explaining the subject selection recommendations.
NOTE: 语文,数学,外语是必修科目不参与组合,advise选的组合都是选修科目,只要选一个组合就行,让你放回多个是为了推荐.

STUDENT INFO:
学科能力排序: "{{ability_ranking_text}}"
兴趣排序: "{{interest_ranking_text}}"
时间安排排序: "{{time_planning_text}}"

INPUT:
"{{question}}" 

OUTPUT:
```json
{
    "answer": "{{gen 'answer' max_tokens=150 temperature=0 stop='"'}}",
    "advise": "{{gen 'advise' max_tokens=240 temperature=0 stop='"'}}",
    "explain": "{{gen 'explain' max_tokens=240 temperature=0 stop='"'}}"
}```""")

def explain_an0(rankings: list) -> dict:
    """
    Analyzes a student's preference or ability ranking and returns explanations and advice based on the radar chart.
    
    Args:
        rankings (list): A structured list of the student's subjects and their percentage scores.
    
    Returns:
        dict: Contains 'explain' and 'advise' fields with respective information.
    """
    output = AN0_PROMPT(ranking_text=format_answer(rankings), caching=True)
    json_str = str(output).split("```json")[1][:-3]
    json_obj = json.loads(json_str)
    
    return json_obj

def explain_an1(interests: list) -> dict:
    """
    Analyzes a student's interest word cloud and returns explanations and advice.
    
    Args:
        interests (list): A structured list of the student's interests with their frequency proportion.
    
    Returns:
        dict: Contains 'explain' and 'advise' fields with respective information.
    """
    output = AN1_PROMPT(interests_text=format_answer(interests), caching=True)
    json_str = str(output).split("```json")[1][:-3]
    json_obj = json.loads(json_str)
    return json_obj

def explain_an2(time_plannings: list) -> dict:
    """
    Analyzes a student's time planning and returns explanations and advice based on the treemap.
    
    Args:
        time_plannings (list): A structured list of the student's activities and their time proportion.
    
    Returns:
        dict: Contains 'explain' and 'advise' fields with respective information.
    """
    output = AN2_PROMPT(time_planning_text=format_answer(time_plannings), caching=True)
    json_str = str(output).split("```json")[1][:-3]
    json_obj = json.loads(json_str)
    return json_obj

def gen_an2(time_planning_text: str) -> dict:
    """
    Analyzes a student's time planning based on their response and returns a structured result or an error.
    
    Args:
        time_planning_text (str): Student's response to their time planning, in Chinese.
    
    Returns:
        dict: Contains either 'result' or 'error' field based on the analysis.
    """
    output = GEN_AN2_PROMPT(time_planning_text=time_planning_text, caching=True)
    json_str = str(output).split("OUTPUT:")[1][:]
    json_obj = json.loads(json_str)
    
    return json_obj

def gen_analysis(rankings: list, interests: list, time_plannings: list, question: str) -> str:
    output = ANALYSIS_PROMPT(
        ability_ranking_text=format_answer([r for r in rankings if r["label"] not in ["语文", "数学", "外语"]]),
        interest_ranking_text=format_answer(interests), 
        time_planning_text=format_answer(time_plannings), 
        question=question,
        caching=True
    )
    json_str = str(output).split("```json")[1][:-3]
    json_obj = json.loads(json_str)
    return json_obj